﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ExtAppBuilder.Ext.Configuration;

namespace ExtAppBuilder.Ext.Util
{
    /// <summary>
    /// Base class that provides a common interface for publishing events. 
    /// Subclasses are expected to to have a property "events" with all the events defined, and, optionally, 
    /// a property "listeners" with configured listeners defined
    /// </summary>
    public class Observable
    {
        /// <summary>
        /// Initializes the observable
        /// </summary>
        /// <param name="config">Configuration to be used while initializing</param>
        public Observable(ObservableConfig config)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        ///  Starts capture on the specified Observable. 
        ///  All events will be passed to the supplied function with the event name + standard signature 
        ///  of the event before the event is fired. 
        ///  If the supplied function returns false, the event will not fire.
        /// </summary>
        /// <param name="o">The Observable to capture</param>
        /// <param name="fn">The function to call</param>
        /// <param name="scope">The scope (this object) for the fn</param>
        public static void Capture(Observable o, object fn, object scope)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        ///  Starts capture on the specified Observable. 
        ///  All events will be passed to the supplied function with the event name + standard signature 
        ///  of the event before the event is fired. 
        ///  If the supplied function returns false, the event will not fire.
        /// </summary>
        /// <param name="o">The Observable to capture</param>
        /// <param name="fn">The function to call</param>
        /// <param name="scope">The scope (this object) for the fn</param>
        public static void Capture(Observable o, object fn)
        {
            Observable.Capture(o, fn, null);                      
        }

        /// <summary>
        /// Sets observability on the passed class constructor. 
        /// This makes any event fired on any instance of the passed class also fire a single event 
        /// through the class allowing for central handling of events on many instances at once.
        /// </summary>
        /// <param name="c">The class constructor to make observable.</param>
        public static void ObserveClass(object c)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Removes all added captures from the Observable
        /// </summary>
        /// <param name="o"></param>
        public static void ReleaseCapture(object o)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Used to define events on this Observable
        /// </summary>
        /// <param name="eventsObject">The object with the events defined</param>
        public void AddEvents(object eventsObject)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Appends an event handler to this object.
        /// </summary>
        /// <param name="eventName">The name of the event to listen for.</param>
        /// <param name="handler">The method the event invokes.</param>
        /// <param name="scope">The scope (this reference) in which the handler function is executed</param>
        /// <param name="options">An object containing handler configuration properties.</param>        
        public void AddListener(string eventName, object handler, string scope, object options)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Appends an event handler to this object.
        /// </summary>
        /// <param name="eventName">The name of the event to listen for.</param>
        /// <param name="handler">The method the event invokes.</param>
        /// <param name="scope">The scope (this reference) in which the handler function is executed</param>
        public void AddListener(string eventName, object handler, string scope)
        {
            AddListener(eventName, handler, scope, null);
        }

        /// <summary>
        /// Appends an event handler to this object.
        /// </summary>
        /// <param name="eventName">The name of the event to listen for.</param>
        /// <param name="handler">The method the event invokes.</param>        
        /// <param name="options">An object containing handler configuration properties.</param> 
        public void AddListener(string eventName, object handler, object options)
        {
            AddListener(eventName, handler, null, options);
        }

        /// <summary>
        /// Appends an event handler to this object.
        /// </summary>
        /// <param name="eventName">The name of the event to listen for.</param>
        /// <param name="handler">The method the event invokes.</param>       
        public void AddListener(string eventName, object handler)
        {
            AddListener(eventName, handler, null, null);
        }

        /// <summary>
        /// Used to enable bubbling of events
        /// </summary>
        /// <param name="events">The events to enable bubbling on</param>
        public void EnableBubble(object events)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Fires the specified event with the passed parameters.
        /// An event may be set to bubble up an Observable parent hierarchy (See Ext.Component.GetBubbleTarget) 
        /// by calling EnableBubble.
        /// </summary>
        /// <param name="eventName">The name of the event to fire.</param>
        /// <param name="parameters">Variable number of parameters are passed to handlers.</param>
        /// <returns>returns false if any of the handlers return false otherwise it returns true.</returns>
        public bool FireEvent(string eventName, params object[] parameters)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Checks to see if this object has any listeners for a specified event
        /// </summary>
        /// <param name="eventName">The name of the event to check for</param>
        /// <returns>True if the event is being listened for, else false</returns>
        public bool HasListener(string eventName)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Appends an event handler to this object (shorthand for addListener).
        /// </summary>
        /// <param name="eventName">The name of the event to listen for.</param>
        /// <param name="handler">The method the event invokes.</param>
        /// <param name="scope">The scope (this reference) in which the handler function is executed</param>
        /// <param name="options">An object containing handler configuration properties.</param>        
        public void On(string eventName, object handler, string scope, object options)
        {
            AddListener(eventName, handler, scope, options);
        }

        /// <summary>
        /// Appends an event handler to this object (shorthand for addListener).
        /// </summary>
        /// <param name="eventName">The name of the event to listen for.</param>
        /// <param name="handler">The method the event invokes.</param>
        /// <param name="scope">The scope (this reference) in which the handler function is executed</param>
        public void On(string eventName, object handler, string scope)
        {
            AddListener(eventName, handler, scope, null);
        }

        /// <summary>
        /// Appends an event handler to this object (shorthand for addListener).
        /// </summary>
        /// <param name="eventName">The name of the event to listen for.</param>
        /// <param name="handler">The method the event invokes.</param>        
        /// <param name="options">An object containing handler configuration properties.</param> 
        public void On(string eventName, object handler, object options)
        {
            AddListener(eventName, handler, null, options);
        }

        /// <summary>
        /// Appends an event handler to this object (shorthand for addListener).
        /// </summary>
        /// <param name="eventName">The name of the event to listen for.</param>
        /// <param name="handler">The method the event invokes.</param>       
        public void On(string eventName, object handler)
        {
            AddListener(eventName, handler, null, null);
        }

        /// <summary>
        /// Removes all listeners for this object
        /// </summary>
        public void PurgeListeners()
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Relays selected events from the specified Observable as if the events were fired by this.
        /// </summary>
        /// <param name="o">The Observable whose events this object is to relay.</param>
        /// <param name="eventNames">Array of event names to relay.</param>
        public void RelayEvents(object o, string[] eventNames)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Removes an event handler.
        /// </summary>
        /// <param name="eventName">The type of event the handler was associated with.</param>
        /// <param name="handler">The handler to remove. This must be a reference to the function passed into the addListener call.</param>
        /// <param name="scope">The scope originally specified for the handle</param>
        public void RemoveListener(string eventName, object handler, object scope)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Removes an event handler.
        /// </summary>
        /// <param name="eventName">The type of event the handler was associated with.</param>
        /// <param name="handler">The handler to remove. This must be a reference to the function passed into the addListener call.</param>        
        public void RemoveListener(string eventName, object handler)
        {
            RemoveListener(eventName, handler, null);
        }

        /// <summary>
        /// Resume firing events. (see suspendEvents) 
        /// If events were suspended using the queueSuspended parameter, then all events fired 
        /// during event suspension will be sent to any listeners now.
        /// </summary>
        public void ResumeEvents()
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Suspend the firing of all events. (see resumeEvents)
        /// </summary>
        /// <param name="queueSuspended">Pass as true to queue up suspended events to be fired after the resumeEvents call instead of discarding all suspended events;</param>
        public void SuspendEvents(bool queueSuspended)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Removes an event handler (shorthand for removeListener.)
        /// </summary>
        /// <param name="eventName">The type of event the handler was associated with.</param>
        /// <param name="handler">The handler to remove. This must be a reference to the function passed into the addListener call.</param>
        /// <param name="scope">The scope originally specified for the handle</param>
        public void Un(string eventName, object handler, object scope)
        {
            RemoveListener(eventName, handler, scope);
        }

        /// <summary>
        /// Removes an event handler (shorthand for removeListener.)
        /// </summary>
        /// <param name="eventName">The type of event the handler was associated with.</param>
        /// <param name="handler">The handler to remove. This must be a reference to the function passed into the addListener call.</param>        
        public void Un(string eventName, object handler)
        {
            RemoveListener(eventName, handler, null);
            Observable x = new Observable(new ObservableConfig());            
        }        

    }
}
